home *** CD-ROM | disk | FTP | other *** search
/ Delphi Developer's Kit 1996 / Delphi Developer's Kit 1996.iso / power / arrays / fastmem.pas < prev    next >
Pascal/Delphi Source File  |  1995-12-22  |  12KB  |  461 lines

  1. {+------------------------------------------------------------
  2.  | Unit FastMem
  3.  |
  4.  | Version: 1.0  Last modified: 05/11/95, 16:47:25
  5.  | Author : P. Below
  6.  | Project: Common utilities
  7.  | Description:
  8.  |   This Unit contains a number of routines to do memory moves,
  9.  |   fills and swaps as fast as possible. The routines are all
  10.  |   implemented in assembler; the Win32-version will generate
  11.  |   different code from the Win16 version.
  12.  |   WARNING! The Win32 version is totally untested since a
  13.  |   32bit version of Delphi is not yet available!
  14.  |
  15.  |   This version will compile as is in BP 7
  16.  +------------------------------------------------------------}
  17. Unit FastMem;
  18. Interface
  19. {$IFDEF VER70}
  20. Type
  21.   Cardinal = Word;
  22. {$ENDIF}
  23.   Procedure MemFill(pTarget: Pointer; numBytes: Cardinal; value: Byte );
  24.   Procedure MemWordFill(pTarget: Pointer; numWords: Cardinal; value: Word );
  25.   Procedure MemDWordFill(pTarget: Pointer; 
  26.                          numDWords: Cardinal; value: LongInt );
  27.   Procedure MemMove(pSource, pTarget: Pointer; numBytes: Cardinal);
  28.   Procedure MemSwap(pSource, pTarget: Pointer; numBytes: Cardinal );
  29.  
  30. Implementation
  31.  
  32. {************************************************************
  33.  * Procedure MemFill
  34.  *
  35.  * Parameters:
  36.  *  pTarget : pointer to memory to fill
  37.  *  numBytes: number of bytes to fill
  38.  *  value   : byte value to fill with
  39.  * Description:
  40.  *  Like System.FillChar, only faster, since it fills in the largest
  41.  *  possible unit (word or dword) as far as possible.
  42.  * Error Conditions:
  43.  *  May generate a GPF if the memory area addressed by pTarget cannot
  44.  *  take numBytes bytes!
  45.  *
  46.  *Created: 05/11/95 16:53:42 by P. Below
  47.  ************************************************************}
  48. Procedure MemFill(pTarget: Pointer; numBytes: Cardinal; value: Byte ); Assembler;
  49. {$IFNDEF WIN32}
  50.     Asm
  51.       mov cx, numBytes
  52.       jcxz @done
  53.       mov al, value
  54.       mov ah, al
  55.       les di, pTarget
  56.       push cx
  57.       cld
  58.       shr cx, 1       (* fill words first *)
  59.       jz @moveone
  60.       rep stosw
  61.     @moveone:         (* fill remaining byte *)
  62.       pop cx
  63.       and cx, 1
  64.       jz  @done
  65.       stosb
  66.     @done:
  67.     End;
  68. {$ELSE}
  69.    { we assume flat memory model here with 32bit near pointers
  70.      and ds=es!
  71.      This code is UNTESTED!
  72.    }
  73.    asm
  74.      mov ecx, numBytes
  75.      or ecx, ecx
  76.      jz @done
  77.      mov al, value
  78.      mov ah, al
  79.      mov bx,ax
  80.      shl eax, 16
  81.      mov ax, bx
  82.      mov edi, pTarget
  83.      cld
  84.      push ecx
  85.      shr ecx, 2   (* fill dwords first *)
  86.      jz @fillrest
  87.      rep stosd
  88.    @fillrest:     (* fill rest bytewise *)
  89.      pop ecx
  90.      and ecx, 3
  91.    @fill:
  92.      jz @done
  93.      mov [ edi ], al
  94.      inc edi
  95.      dec ecx
  96.      jmp @fill
  97.    @done:
  98.    end;
  99. {$ENDIF}
  100.  
  101. {************************************************************
  102.  * Procedure MemWordFill
  103.  *
  104.  * Parameters:
  105.  *  pTarget : pointer to memory to fill
  106.  *  numWords: number of words to fill
  107.  *  value   : word value to fill with
  108.  * Description:
  109.  *  Fills the target memory area with numWords copies of value.
  110.  * Error Conditions:
  111.  *  May generate a GPF if the memory area addressed by pTarget cannot
  112.  *  take numWord words!
  113.  *
  114.  *Created: 05/11/95 16:53:42 by P. Below
  115.  ************************************************************}
  116. Procedure MemWordFill(pTarget: Pointer; numWords: Cardinal; value: Word );
  117.   Assembler;
  118. {$IFNDEF WIN32}
  119.     Asm
  120.       mov cx, numWords
  121.       jcxz @done
  122.       mov ax, value
  123.       les di, pTarget
  124.       cld
  125.       rep stosw
  126.     @done:
  127.     End;
  128. {$ELSE}
  129.    { we assume flat memory model here with 32bit near pointers
  130.      and ds=es!
  131.      This code is UNTESTED!
  132.    }
  133.    asm
  134.      mov ecx, numWords
  135.      or ecx, ecx
  136.      jz @done
  137.      mov ax, value
  138.      mov bx,ax
  139.      shl eax, 16
  140.      mov ax, bx
  141.      mov edi, pTarget
  142.      cld
  143.      push ecx
  144.      shr ecx, 1   (* fill dwords first *)
  145.      jz @fillrest
  146.      rep stosd
  147.    @fillrest:     (* fill rest *)
  148.      pop ecx
  149.      and ecx, 1
  150.      jz @done
  151.      mov [ edi ], ax
  152.    @done:
  153.    end;
  154. {$ENDIF}
  155.  
  156. {************************************************************
  157.  * Procedure MemDWordFill
  158.  *
  159.  * Parameters:
  160.  *  pTarget  : pointer to memory to fill
  161.  *  numDWords: number of dwords to fill
  162.  *  value    : dword value to fill with
  163.  * Description:
  164.  *  Fills the target memory area with numDWords copies of value.
  165.  * Error Conditions:
  166.  *  May generate a GPF if the memory area addressed by pTarget cannot
  167.  *  take numDWord dwords!
  168.  *
  169.  *Created: 05/11/95 16:53:42 by P. Below
  170.  ************************************************************}
  171. Procedure MemDWordFill(pTarget: Pointer; numDWords: Cardinal; value: LongInt );
  172.   Assembler;
  173. {$IFNDEF WIN32}
  174.     Asm
  175.       mov cx, numDWords
  176.       jcxz @done
  177.       push ds
  178.       mov ax, word ptr value
  179.       mov dx, word ptr value+2
  180.       lds bx, pTarget
  181.     @loop:
  182.       mov [ bx ], ax
  183.       inc bx
  184.       inc bx
  185.       mov [ bx ], dx
  186.       inc bx
  187.       inc bx
  188.       dec cx
  189.       jnz @loop
  190.       pop ds
  191.     @done:
  192.     End;
  193. {$ELSE}
  194.    { we assume flat memory model here with 32bit near pointers
  195.      and ds=es!
  196.      This code is UNTESTED!
  197.    }
  198.    asm
  199.      mov ecx, numDWords
  200.      or ecx, ecx
  201.      jz @done
  202.      mov eax, value
  203.      mov edi, pTarget
  204.      cld
  205.      rep stosd
  206.    @done:
  207.    end;
  208. {$ENDIF}
  209.  
  210. Function CheckOverlap: Boolean; Assembler;
  211.   Asm
  212. {$IFNDEF WIN32}
  213.     (* assumes: ds:si source pointer, es:di target pointer
  214.                 cx number of bytes to copy.
  215.        returns: al = 0 if no overlap,
  216.                 al = 1 if overlap, in which case the pointers
  217.                 are returned corrected! *)
  218.     mov ax, ds     (* compare the selectors *)
  219.     mov bx, es
  220.     cmp ax, bx
  221.     jne @no_overlap
  222.     mov ax, si     (* selectors equal, check offset parts *)
  223.     cmp ax, di     (* target <= source is never a problem *)
  224.     jnb @no_overlap
  225.     add ax, cx     (* check for source+count > target, which signifies *)
  226.     cmp ax, di     (* problematic overlap *)
  227.     jna @no_overlap
  228.     mov ax, 1      (* we have overlap, correct pointers to point at *)
  229.     add si, cx     (* last byte in source and target range *)
  230.     add di, cx
  231.     dec si
  232.     dec di
  233.     jmp @done
  234.   @no_overlap:
  235.     sub ax, ax
  236.   @done:
  237. {$ELSE}
  238.     (* assumes: esi source pointer, edi target pointer
  239.                 ecx number of bytes to copy.
  240.        returns: al = 0 if no overlap,
  241.                 al = 1 if overlap, in which case the pointers
  242.                 are returned corrected! *)
  243.     mov eax, esi     (* selectors equal by default, check offset parts *)
  244.     cmp eax, edi
  245.     jnb @no_overlap
  246.     add eax, ecx     (* for source+count > target, which signifies *)
  247.     cmp eax, edi     (* overlap *)
  248.     jna @no_overlap
  249.     mov eax, 1
  250.     add esi, ecx
  251.     add edi, ecx
  252.     dec esi
  253.     dec edi
  254.     jmp @done
  255.   @no_overlap:
  256.     sub eax, eax
  257.   @done:
  258. {$ENDIF}
  259.   End;
  260.  
  261. {************************************************************
  262.  * Procedure MemMove
  263.  *
  264.  * Parameters:
  265.  *  pSource  : pointer to source memory
  266.  *  pTarget  : pointer to target memory
  267.  *  numBytes : number of bytes to copy
  268.  * Description:
  269.  *  Like System.Move, only faster for larger numbers of bytes, 
  270.  *  since it does the copy word or dword-wise, as far as possible.
  271.  *  The procedure checks for overlap of source and target regions
  272.  *  and performs the copy from highest address backwards, if the
  273.  *  regions overlap in a problematic way. The logic is optimized
  274.  *  for the source address beeing even (data word or dword-aligned).
  275.  *
  276.  * Error Conditions:
  277.  *  May cause a GPF if the memory addressed by the pointers has
  278.  *  a size of less than numBytes bytes.
  279.  *
  280.  *Created: 05/11/95 16:58:34 by P. Below
  281.  ************************************************************}
  282. Procedure MemMove(pSource, pTarget: Pointer; numBytes: Cardinal); Assembler;
  283. {$IFNDEF WIN32}
  284.   Asm
  285.     push ds
  286.     mov cx, numBytes
  287.     jcxz @done
  288.     lds si, pSource
  289.     les di, pTarget
  290.     call CheckOverlap
  291.     or al,al
  292.     jnz @overlap
  293.     cld             (* address ascending *)
  294.     push cx
  295.     shr cx, 1       (* move words first *)
  296.     jz @moveone
  297.     rep movsw
  298.   @moveone:         (* move remaining byte *)
  299.     pop cx
  300.     and cx, 1
  301.     jz  @done
  302.     movsb
  303.     jmp @done
  304.  
  305.   @overlap:
  306.     std
  307.     test cx, 1      (* check for odd count of bytes *)
  308.     je @moverest
  309.     movsb           (* if odd, move one byte first *)
  310.   @moverest:
  311.     shr cx, 1       (* count is now in words *)
  312.     jz @done
  313.     dec si
  314.     dec di
  315.     rep movsw       (* move rest as words *)
  316.     cld
  317.  
  318.   @done:
  319.     pop ds
  320.   End;
  321. {$ELSE}
  322.    { we assume flat memory model here with 32bit near pointers
  323.      and ds=es!
  324.      This code is UNTESTED!
  325.    }
  326.   asm
  327.     mov ecx, numBytes
  328.     or ecx, ecx
  329.     jz @done
  330.     mov esi, pSource
  331.     mov edi, pTarget
  332.     call CheckOverlap
  333.     or al,al
  334.     jnz @overlap
  335.     cld
  336.     push ecx
  337.     shr ecx, 2   (* move dwords first *)
  338.     jz @moverest
  339.     rep movsd
  340.   @moverest:     (* move rest bytewise *)
  341.     pop ecx
  342.     and ecx, 3
  343.     jz @done
  344.     rep movsb
  345.     jmp @done
  346.  
  347.   @overlap:
  348.     std
  349.     test ecx, 1     (* check for odd count of bytes *)
  350.     jz @move2
  351.     movsb           (* if odd, move one byte first *)
  352.   @move2:
  353.     shr ecx, 1
  354.     dec esi
  355.     dec edi
  356.     jz @done
  357.     test ecx, 1     (* check for odd count of words *)
  358.     jz @move3
  359.     movsw           (* if yes, move one word *)
  360.   @move3:
  361.     shr ecx, 1
  362.     jz @done
  363.     dec esi,2
  364.     dec edi,2
  365.     rep movsd
  366.     cld
  367.  
  368.   @done:
  369.   end;
  370. {$ENDIF}
  371.  
  372. {************************************************************
  373.  * Procedure MemSwap
  374.  *
  375.  * Parameters:
  376.  *  pSource  : pointer to source memory
  377.  *  pTarget  : pointer to target memory
  378.  *  numBytes : number of bytes to swap
  379.  * Description:
  380.  *  exchanges the contents of the memory addressed by the two
  381.  *  pointers. These areas should never overlap or the results
  382.  *  will invariably be somewhat strange! 
  383.  * Error Conditions:
  384.  *  May cause a GPF if the memory addressed by the pointers has
  385.  *  a size of less than numBytes bytes.
  386.  *
  387.  *Created: 05/11/95 16:58:34 by P. Below
  388.  ************************************************************}
  389. Procedure MemSwap(pSource, pTarget: Pointer; numBytes: Cardinal ); Assembler;
  390. {$IFNDEF WIN32}
  391.     Asm
  392.       push ds
  393.       mov cx, numBytes
  394.       jcxz @done
  395.       lds si, pSource
  396.       les di, pTarget
  397.       cmp cx, 1
  398.       je @swapone
  399.     @loop:
  400.       mov ax, [ si ]
  401.       xchg ax, es:[ di ]
  402.       mov [ si ], ax
  403.       inc si
  404.       inc si
  405.       inc di
  406.       inc di
  407.       dec cx
  408.       dec cx
  409.       jz @done
  410.       cmp cx, 1
  411.       ja @loop
  412.     @swapone:
  413.       mov al, [ si ]
  414.       xchg al, es:[ di ]
  415.       mov [ si ], al
  416.     @done:
  417.       pop ds
  418.     End;
  419. {$ELSE}
  420.    { we assume flat memory model here with 32bit near pointers
  421.      and ds=es!
  422.      This code is UNTESTED!
  423.    }
  424.    asm
  425.      mov ecx, numBytes
  426.      or ecx, ecx
  427.      jz @done
  428.      mov esi, pSource
  429.      mov edi, pTarget
  430.      cmp ecx, 3
  431.      jna @swapremains
  432.    @loop:
  433.      mov eax, [ esi ]
  434.      xchg eax, [ edi ]
  435.      mov [ esi ], eax
  436.      inc esi, 4
  437.      inc edi, 4
  438.      dec ecx, 4
  439.      jz @done
  440.      cmp ecx, 3
  441.      ja @loop
  442.    @swapremains:
  443.      cmp ecx, 1
  444.      je @swapone
  445.      mov ax, [ esi ]
  446.      xchg ax, [ edi ]
  447.      mov [ esi ], ax
  448.      inc esi, 2
  449.      inc edi, 2
  450.      dec ecx, 2
  451.      jz @done
  452.    @swapone:
  453.      mov al, [ esi ]
  454.      xchg al, [ edi ]
  455.      mov [ esi ], al
  456.    @done:
  457.    end;
  458. {$ENDIF}
  459.  
  460. End.
  461.